{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.5 Spaces and forms on subdomains\n",
    "     \n",
    "\n",
    "In NGSolve, finite element spaces can be defined on subdomains. This is useful for multiphysics problems like fluid-structure interaction.\n",
    "\n",
    "In addition, bilinear or linear forms can be defined as integrals over regions. *Regions* are parts of the domain. They may be subdomains, or  parts of the domain boundary, or parts of subdomain interfaces.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import netgen.gui\n",
    "%gui tk\n",
    "from netgen.geom2d import *\n",
    "from ngsolve import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Naming subdomains and boundaries"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We define a geometry with multiple regions and assign names to these regions below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "geo = SplineGeometry()\n",
    "geo.AddRectangle((0,0), (2,2),\n",
    "                 bcs=[\"b\",\"r\",\"t\",\"l\"],\n",
    "                 leftdomain=1)\n",
    "geo.AddRectangle((1,0.9), (1.3,1.4),\n",
    "                 bcs=[\"b2\",\"r2\",\"t2\",\"l2\"],\n",
    "                 leftdomain=2, rightdomain=1)\n",
    "geo.SetMaterial (1, \"outer\")\n",
    "geo.SetMaterial (2, \"inner\")\n",
    "mesh = Mesh(geo.GenerateMesh(maxh=0.1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "* These statements define two rectangular subdomain regions named \"inner\", \"outer\".\n",
    "\n",
    "* The bottom, right, top and left parts of the outer rectangle's boundaries define boundary regions, respectively labeled  \"b\", \"r\", \"t\", \"l\".\n",
    "\n",
    "* Similarly, the bottom, right, top and left parts of the inner rectangle's boundaries are regions named \"b2\", \"r2\", \"t2\", \"l2\".\n",
    "\n",
    "* When you select the `Mesh` tab in the Netgen window's Graphical User Interface (GUI) and double click on a point, the two subdomains are rendered in different colors. (You should also see the subdomain outlines in the Netgen window when you select the `Geometry` tab.)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A finite element space on a subdomain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "fes1 = H1(mesh, definedon=\"inner\")\n",
    "\n",
    "u1 = GridFunction(fes1, \"u1\")\n",
    "u1.Set(x*y)\n",
    "Draw(u1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note how $u_1$ is displayed only in the `inner` region. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Integrating on regions "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You have already seen how boundary regions are used in setting Dirichlet boundary conditions.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "fes = H1(mesh, order=3, dirichlet=\"b|l|r\")\n",
    "\n",
    "u, v = fes.TnT()\n",
    "gfu = GridFunction(fes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Boundary regions or subdomains can also serve as domains of integration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = LinearForm(fes)\n",
    "f += SymbolicLFI(u1*v, definedon=mesh.Materials(\"inner\"))\n",
    "f += SymbolicLFI(0.1*v, definedon=mesh.Boundaries(\"t\"))\n",
    "f.Assemble()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here the functional $f$ is defined as a sum of two integrals, one over the inner subdomain, and another over the top boundary:\n",
    "$$\n",
    "f(v) = \\int_{\\Omega_{inner}} u_1 v \\; dx + \\int_{\\Gamma_{top}} \\frac{v}{10}\\; ds\n",
    "$$\n",
    "\n",
    "*Note:* `SymbolicLFI` has no information about the mesh. Hence its not  enough to  give it the just the name of the region (\"inner\", or \"t\").  We must give it the region objects (named by the \"inner\" and \"t\" labels) using the `definedon` flag.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = BilinearForm(fes)\n",
    "a += SymbolicBFI(grad(u)*grad(v))\n",
    "a.Assemble()\n",
    "\n",
    "# Solve the problem:\n",
    "gfu.vec.data = a.mat.Inverse(fes.FreeDofs()) * f.vec\n",
    "Draw (gfu)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### More about region objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('outer', 'inner')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mesh.GetMaterials()    # list all subdomains"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('b', 'r', 't', 'l', 'b2', 'r2', 't2', 'l2')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mesh.GetBoundaries()   # list boundary/interface regions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ngsolve.comp.Region at 0x7f1a3434bf10>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mesh.Materials(\"inner\") # look at object's type "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ngsolve.comp.Region at 0x7f1a3434b8f0>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mesh.Boundaries(\"t\")    # same type!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Operations with regions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Print region information:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: 01\n",
      "0: 11\n",
      "0: 00110000\n"
     ]
    }
   ],
   "source": [
    "print(mesh.Materials(\"inner\").Mask())\n",
    "print(mesh.Materials(\"[a-z]*\").Mask())  # can use regexp\n",
    "print(mesh.Boundaries('t|l').Mask())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add regions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: 11\n"
     ]
    }
   ],
   "source": [
    "io = mesh.Materials(\"inner\") + mesh.Materials(\"outer\")\n",
    "print(io.Mask())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Take complement of a region:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: 10\n"
     ]
    }
   ],
   "source": [
    "c = ~mesh.Materials(\"inner\")\n",
    "print(c.Mask())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Subtract regions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: 01\n"
     ]
    }
   ],
   "source": [
    "diff = mesh.Materials(\"inner|outer\") - mesh.Materials(\"outer\")\n",
    "print(diff.Mask())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set a piecewise constant `CoefficientFunction` using the subdomains:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "domain_values = {'inner': 3.7,  'outer': 1}\n",
    "values_list = [domain_values[mat]\n",
    "               for mat in mesh.GetMaterials()]\n",
    "cf = CoefficientFunction(values_list)\n",
    "Draw(cf, mesh, 'piecewise')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Coefficients on boundary regions are given similarly. Let's make a linear function that equals 2 at the bottom right vertex of current domain (0,2) x (0,2) and equals zero at the remaining vertices. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "bdry_values = {'b': x, 'r': 2-y}\n",
    "values_list = [bdry_values[bc]\n",
    "               if bc in bdry_values.keys() else 0\n",
    "               for bc in mesh.GetBoundaries()]\n",
    "cf = CoefficientFunction(values_list)\n",
    "Draw(cf, mesh, 'piecewise')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Pitfall!* Look at the GUI output. Is this what we expected?\n",
    "\n",
    "What happened here? The object `cf` has no information on boundary regions, so it cannot associate the list of values to boundary regions. By default, the list of values are assumed to be subdomain values.\n",
    "\n",
    "To associate these values to boundary regions, we use a `GridFunction` and `Set`, which also lets us view an extension of these boundary values into the domain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = GridFunction(H1(mesh), name='bdry')\n",
    "g.Set(cf, definedon=~mesh.Boundaries(''))\n",
    "Draw(g, max=2, min=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you think that specifying the whole boundary using\n",
    "\n",
    "    ~mesh.Boundaries('')\n",
    "\n",
    "is convoluted, then you may use\n",
    "\n",
    "    g.Set(cf, definedon=mesh.Boundaries('b|r')).\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "g.Set(cf, definedon=mesh.Boundaries('b|r'))\n",
    "Redraw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What happens if you `Set` using `b` and then on `r`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "g.Set(cf, definedon=mesh.Boundaries('b'))\n",
    "g.Set(cf, definedon=mesh.Boundaries('r'))\n",
    "Redraw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Pitfall!* We see an unexpected behavior in the GUI. This is because each `Set` begins by zeroing the grid function - so any previous values are lost!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What happens if you use\n",
    "\n",
    "    g.Set(cf, BND)\n",
    "    \n",
    "instead?\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = GridFunction(H1(mesh))\n",
    "g.Set(cf, BND)\n",
    "Draw(g, max=2, min=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Pitfall!* We do not obtain the previous result because the keyword `BND` directs `Set` to only set the data in boundary regions marked as `dirichlet`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = GridFunction(H1(mesh, dirichlet='b|r'))\n",
    "g.Set(cf, BND)\n",
    "Draw(g, max=2, min=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Unused dofs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Its important not to get confused with the `ndof` of spaces defined on subdomains. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(504, 504)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fes1 = H1(mesh, definedon=\"inner\")\n",
    "fes = H1(mesh)\n",
    "fes1.ndof, fes.ndof"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thus the `ndof`s are the same for spaces on one  subdomain and the whole domain.\n",
    "\n",
    "However, `FreeDofs` show that the real number of degrees of freedom for the subdomain space is much smaller:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0: 00001111000000000000000000000000000000000000000000\n",
      "50: 00000000000000000000000000000000001111111111111100\n",
      "100: 00000000000000000000000000000000000000000000000000\n",
      "150: 00000000000000000000000000000000000000000000000000\n",
      "200: 00000000000000000000000000000000000000000000000000\n",
      "250: 00000000000000000000000000000000000000000000000000\n",
      "300: 00000000000000000000000000000000000000000000000000\n",
      "350: 00000000000000000000000000000000000000000000000000\n",
      "400: 00000000000000000000000000000000000000000000000000\n",
      "450: 00000000000000000000000000000000000000011111111111\n",
      "500: 1111\n"
     ]
    }
   ],
   "source": [
    "print(fes1.FreeDofs())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One can also glean this information by examining `CouplingType` of each degrees of freedom of the space, which reveals that there are many unknowns of type `COUPLING_TYPE.UNUSED_DOF`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.UNUSED_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n",
      "COUPLING_TYPE.WIREBASKET_DOF\n"
     ]
    }
   ],
   "source": [
    "for i in range(fes1.ndof):\n",
    "    print(fes1.CouplingType(i))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We shall learn about the other types of dofs you see here in other tutorial sections. "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
